/*
 *    Copyright © OpenAtom Foundation.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package com.inspur.edp.udt.designtime.api.entity;

import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.inspur.edp.caf.cef.schema.datatype.StructuredType;
import com.inspur.edp.cef.designtime.api.element.EnumIndexType;
import com.inspur.edp.cef.designtime.api.entity.GspCommonField;
import com.inspur.edp.lcm.metadata.api.IMetadataContent;
import com.inspur.edp.udt.designtime.api.entity.dbInfo.ColumnInfo;
import com.inspur.edp.udt.designtime.api.entity.dbInfo.ColumnMapType;
import com.inspur.edp.udt.designtime.api.entity.dbInfo.UdtDbInfo;
import com.inspur.edp.udt.designtime.api.entity.element.ElementCollection;
import com.inspur.edp.udt.designtime.api.entity.enumtype.UseType;
import com.inspur.edp.udt.designtime.api.entity.property.PropertyCollection;
import com.inspur.edp.udt.designtime.api.json.ComplexDataTypeDeserializer;
import com.inspur.edp.udt.designtime.api.json.ComplexDataTypeSerializer;
import com.inspur.edp.udt.designtime.api.utils.UdtUtils;
import com.inspur.edp.cef.designtime.api.collection.CommonDtmCollection;
import com.inspur.edp.cef.designtime.api.collection.CommonValCollection;
import com.inspur.edp.cef.designtime.api.element.GspElementDataType;
import com.inspur.edp.cef.designtime.api.element.GspElementObjectType;
import com.inspur.edp.cef.designtime.api.collection.GspAssociationCollection;
import com.inspur.edp.cef.designtime.api.collection.GspEnumValueCollection;
import com.inspur.edp.cef.designtime.api.IFieldCollection;
import com.inspur.edp.cef.designtime.api.IGspCommonField;
import com.inspur.edp.cef.designtime.api.entity.DataTypeAssemblyInfo;
import com.inspur.edp.cef.designtime.api.entity.ClassInfo;

import java.util.List;

/**
 * 复杂类型Udt
 */
@JsonDeserialize(using = ComplexDataTypeDeserializer.class)
@JsonSerialize(using = ComplexDataTypeSerializer.class)
public class ComplexDataTypeDef extends UnifiedDataTypeDef implements IMetadataContent {
	///#region 私有属性

	private CommonDtmCollection dtmBeforeSave;
	private CommonDtmCollection dtmAfterCreate;
	private CommonDtmCollection dtmAfterModify;
	private CommonValCollection valBeforeSave;
	private CommonValCollection valAfterModify;
	///#endregion

	///#region 构造函数

	public ComplexDataTypeDef() {
		UdtDbInfo tempVar = new UdtDbInfo();
		tempVar.setMappingType(ColumnMapType.SingleColumn);
		setDbInfo(tempVar);
		setElements(new ElementCollection());
		initData();

	}

	/**
	 * 字段集合
	 * <see cref="ElementCollection"/>
	 */
	private ElementCollection privateElements;

	public final ElementCollection getElements() {
		if(privateElements==null)
			privateElements=new ElementCollection();
		return privateElements;
	}

	public final void setElements(ElementCollection value) {
		privateElements = value;
	}

	/**
	 * 数据库配置信息
	 * <see cref="UdtDbInfo"/>
	 */
	private UdtDbInfo privateDbInfo;

	public final UdtDbInfo getDbInfo() {
		return privateDbInfo;
	}

	public final void setDbInfo(UdtDbInfo value) {
		privateDbInfo = value;
	}

	/**
	 * 排序条件
	 * <see cref="string"/>
	 */
	private String privateOrderbyCondition;

	public final String getOrderbyCondition() {
		return privateOrderbyCondition;
	}

	public final void setOrderbyCondition(String value) {
		privateOrderbyCondition = value;
	}

	/**
	 * 过滤条件
	 * <see cref="string"/>
	 */
	private String privateFilterCondition;

	public final String getFilterCondition() {
		return privateFilterCondition;
	}

	public final void setFilterCondition(String value) {
		privateFilterCondition = value;
	}

	/**
	 * 是否只读
	 * <see cref="bool"/>
	 */
	private boolean privateIsReadOnly;

	public final boolean getIsReadOnly() {
		return privateIsReadOnly;
	}

	public final void setIsReadOnly(boolean value) {
		privateIsReadOnly = value;
	}

	/**
	 * 是否虚拟
	 * <see cref="bool"/>
	 */
	private boolean privateIsVirtual;

	public final boolean getIsVirtual() {
		return privateIsVirtual;
	}

	public final void setIsVirtual(boolean value) {
		privateIsVirtual = value;
	}

	/**
	 * 是否引用对象
	 * <see cref="bool"/>
	 */
	private boolean privateIsRef;

	public final boolean getIsRef() {
		return privateIsRef;
	}

	public final void setIsRef(boolean value) {
		privateIsRef = value;
	}

	/**
	 * 字段集合
	 * <see cref="IFieldCollection"/>
	 */
	public IFieldCollection getContainElements() {
		return getElements();

	}

	/**
	 * 根据id查找字段
	 *
	 * @param id 待查找字段id
	 * @return 字段
	 */
	public final IGspCommonField findElement(String id) {
		for (IGspCommonField ele : getElements()) {
			if (ele.getID().equals(id)) {
				return ele;
			}
		}
		return null;
	}

	/**
	 * 获取entity程序集的类信息
	 *
	 * @return entity程序集的类信息
	 */
	public final ClassInfo getGeneratedEntityClassInfo() {

		DataTypeAssemblyInfo assembly = this.getEntityAssemblyInfo();
		String classNamespace = assembly.getDefaultNamespace();
		String className = String.format("I%1$s", getCode());
		return new ClassInfo(assembly, className, classNamespace);
	}


	public final void initData() {
		initProperties((PropertyCollection) getPropertys());

	}

	public final void initProperties(PropertyCollection properties) {
//		properties.add(GetPropertyInfo("DataType", GspElementDataType.class, GspElementDataType.String, UseType.AsConstraint, false));
		properties.add(getPropertyInfo("DataType", GspElementDataType.class, GspElementDataType.String, UseType.AsConstraint, false));
		properties.add(getPropertyInfo("Length", Integer.class, 36, UseType.AsConstraint, false));
		properties.add(getPropertyInfo("Precision", Integer.class, 0, UseType.AsConstraint, false));
		properties.add(getPropertyInfo("DefaultValue", String.class, null, UseType.AsConstraint, false));
		properties.add(getPropertyInfo("ObjectType", GspElementObjectType.class, GspElementObjectType.None, UseType.AsConstraint, false)); // 20180802 udt设计时评审，对象类型、关联、枚举为[约束]，且不可更改；
		properties.add(getPropertyInfo("ChildAssociations", GspAssociationCollection.class, null, UseType.AsConstraint, false));
		properties.add(getPropertyInfo("ContainEnumValues", GspEnumValueCollection.class, null, UseType.AsConstraint, false));
		properties.add(getPropertyInfo("IsVirtual", Boolean.class, false, UseType.AsConstraint, false));
		properties.add(getPropertyInfo("IsRequire", Boolean.class, false, UseType.AsConstraint, false));
		properties.add(getPropertyInfo("IsMultiLanguage", Boolean.class, false, UseType.AsConstraint, false));
		properties.add(getPropertyInfo("IsUdt", Boolean.class, false, UseType.AsConstraint, false));
		properties.add(getPropertyInfo("UdtPkgName", String.class, "", UseType.AsConstraint, false));
		properties.add(getPropertyInfo("UdtID", String.class, "", UseType.AsConstraint, false));
		properties.add(getPropertyInfo("EnableRtrim", Boolean.class, false, UseType.AsConstraint, false));
		properties.add(getPropertyInfo("EnumIndexType", EnumIndexType.class, EnumIndexType.Integer, UseType.AsConstraint, false));

	}

	///#endregion

	///#region 更新columns信息

	/**
	 * 更新columns信息
	 * 若包含childElements则直接记录childElements
	 */
	@Override
	public void updateColumnsInfo() {
//		Columns.Clear();
		getColumns().clear();

		// 判断与数据库列的映射方式[单一列]
		if (getDbInfo().getMappingType() == ColumnMapType.SingleColumn) {

			ColumnInfo columnInfo = UdtUtils.convertComplexDataTypeDefToOneColumnInfo(this);

			getColumns().add(columnInfo);
			return;
		}

		if (getElements().size() == 0) {
			return;
		}
		for (IGspCommonField ele : getElements()) {
			if (ele.getChildElements().size() > 0) {
				for (IGspCommonField childEle : ele.getChildElements()) {
					ColumnInfo columnInfo = UdtUtils.convertUdtElementToColumnInfo(childEle);
					getColumns().add(columnInfo);
				}
			} else {
				ColumnInfo columnInfo = UdtUtils.convertUdtElementToColumnInfo(ele);
				getColumns().add(columnInfo);
			}
		}
	}

	// region ValueObjectType
	@Override
	protected void buildElementStructureTypes(List<StructuredType> list) {
		for (IGspCommonField field : getContainElements()) {
			if (field.getIsUdt()) {
				continue;
			}
			if (field.getObjectType() != GspElementObjectType.Enum) {
				continue;
			}
			list.add((StructuredType) ((GspCommonField) field).getPropertyType());
		}
	}
	// endregion
}
